package com.atguigu.gmall.order.controller;

import com.alibaba.fastjson.JSON;
import com.atguigu.gmall.cart.client.CartFeignClient;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.common.util.AuthContextHolder;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.user.UserAddress;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.user.client.UserFeignClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Author LEO
 * @Date 2021年12月19日 17:20
 */
// 订单数据汇总
@RestController
@RequestMapping("api/order")
public class OrderApiController {

    @Autowired
    private CartFeignClient cartFeignClient;

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private OrderService orderService;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    @Autowired
    private RedisTemplate redisTemplate;


    /**
     * 确认订单
     * @param request
     * @return
     */
    @GetMapping("auth/trade")
    public Result<Map<String, Object>> trade(HttpServletRequest request) {
        //获取用户id
        String userId = AuthContextHolder.getUserId(request);
        HashMap<String, Object> map = new HashMap<>();
        // 远程调用获取收货地址
        List<UserAddress> userAddressList = userFeignClient.findUserAddressListByUserId(Long.parseLong(userId));
        //获取送货清单
        List<CartInfo> cartCheckedList = cartFeignClient.getCartCheckedList(userId);

        // 声明一个订单明细
        List<OrderDetail> detailArrayList=new ArrayList<>();
        int totalNum=0;
        // cartCheckedList 集合数据赋值给订单明细集合
        for (CartInfo cartInfo : cartCheckedList) {
            OrderDetail orderDetail = new OrderDetail();
            //赋值
            orderDetail.setSkuId(cartInfo.getSkuId());
            orderDetail.setSkuName(cartInfo.getSkuName());
            orderDetail.setImgUrl(cartInfo.getImgUrl());
            orderDetail.setSkuNum(cartInfo.getSkuNum());
            orderDetail.setOrderPrice(cartInfo.getSkuPrice());
            detailArrayList.add(orderDetail);
            orderDetail.setCreateTime(new Date());
            totalNum+=cartInfo.getSkuNum();
        }
        OrderInfo orderInfo=new OrderInfo();
        orderInfo.setOrderDetailList(detailArrayList);
        //总价格
        map.put("totalAmount",orderInfo.getTotalAmount());
        //  第一种：集合长度  第二种：计算每个skuId 的总件数
        map.put("totalNum",detailArrayList.size());
        map.put("detailArrayList",detailArrayList);
        map.put("userAddressList",userAddressList);

        //获取流水号，并存储
        String tradeNo = orderService.getTradeNo(userId);
        map.put("tradeNo",tradeNo);
        return Result.ok(map);
    }

    // 保存订单
    @PostMapping("auth/submitOrder")
    public Result submitOrder(@RequestBody OrderInfo orderInfo,HttpServletRequest request){
        String userId = AuthContextHolder.getUserId(request);
        orderInfo.setUserId(Long.parseLong(userId));
        //获取页面传递的交易号
        String tradeNo = request.getParameter("tradeNo");
        Boolean result= orderService.checkTradeNo(tradeNo,userId);
//        if (result){
//            // 比较成功可以提交
//        }else {
//            // 不能提交
//
//        }
        //比较失败
        if (!result){
            return Result.fail().message("不能无限刷新回退订单!");
        }
        //删除
        orderService.deleteTradeNo(userId);


        // 可以使用多线程
        CompletableFuture completableFuture=new CompletableFuture();
        List<CompletableFuture> futureList=new ArrayList<>();
         // 存储错误信息的集合
        List<String> errorList=new ArrayList<>();

        // 验库存
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            // 开启  CompletableFuture
            CompletableFuture<Void> stockCompletableFuture = CompletableFuture.runAsync(() -> {
                Boolean flag = orderService.checkStock(orderDetail.getSkuId(), orderDetail.getSkuNum());
                if (!flag) {
                    // 库存不足
//                return Result.fail().message("库存不足！");
                    errorList.add(orderDetail.getSkuName() + "库存不足！");
                }
            },threadPoolExecutor);
            //添加到这个集合
            futureList.add(stockCompletableFuture);

            CompletableFuture<Void> priceCompletableFuture = CompletableFuture.runAsync(() -> {
                // 订单价格
            BigDecimal orderPrice = orderDetail.getOrderPrice();
            //实时价格  @GmallCache 缓存中
            BigDecimal skuPrice = productFeignClient.getSkuPrice(orderDetail.getSkuId());
            // 价格变动
            if (orderPrice.compareTo(skuPrice) !=0){
                // 价格变动，需要更新数据
                cartFeignClient.loadCartCache(userId);
//                return Result.fail().message(orderDetail.getSkuName()+"价格有变动");
                errorList.add(orderDetail.getSkuName() +"价格有变动");
               }
            },threadPoolExecutor);
            //添加到这个集合
            futureList.add(priceCompletableFuture);
        }
        // 所有数据结果：errorList : futureList 执行异步编排的集合
        CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()])).join();
        // 判断 errorList 是否有数据
        if (errorList.size()>0){
            //  return Result.fail().message(orderDetail.getSkuName()+"价格有变动",orderDetail.getSkuName() + "库存不足！");
            return Result.fail().message(StringUtils.join(errorList,","));
        }

//        for (OrderDetail orderDetail : orderDetailList) {
//            Boolean flag = orderService.checkStock(orderDetail.getSkuId(), orderDetail.getSkuNum());
//            if (!flag){
//                // 库存不足
//                return Result.fail().message("库存不足！");
//            }
//            // 订单价格
//            BigDecimal orderPrice = orderDetail.getOrderPrice();
//            //实时价格  @GmallCache 缓存中
//            BigDecimal skuPrice = productFeignClient.getSkuPrice(orderDetail.getSkuId());
//            // 价格变动
//            if (orderPrice.compareTo(skuPrice) !=0){
//                // 价格变动，需要更新数据
//                cartFeignClient.loadCartCache(userId);
//                return Result.fail().message(orderDetail.getSkuName()+"价格有变动");
//            }
//        }
        //提交订单
        Long orderId  =   orderService.saveOrderInfo(orderInfo);


        return Result.ok(orderId);
    }


    /**
     * 内部调用获取订单
     * @param orderId
     * @return
     */
    @GetMapping("inner/getOrderInfo/{orderId}")
    public OrderInfo getOrderInfo(@PathVariable(value = "orderId") Long orderId){
        return orderService.getOrderInfo(orderId);
    }

    // 拆单
    @PostMapping("orderSplit")
    public String orderSplit(HttpServletRequest request){
        // 获取传递过来的参数
        String orderId = request.getParameter("orderId");
        String wareSkuMap = request.getParameter("wareSkuMap");
        //拆单需要
        List<Map> maps=new ArrayList<>();
       List<OrderInfo> orderInfoList= orderService.orderSplit(orderId,wareSkuMap);
        for (OrderInfo orderInfo : orderInfoList) {
            // orderInfo 转map
            Map map = orderService.initWareOrder(orderInfo);
            maps.add(map);
        }
        return JSON.toJSONString(orderInfoList);
    }

    /**
     * 秒杀提交订单，秒杀订单不需要做前置判断，直接下单
     * @param orderInfo
     * @return
     */
    @PostMapping("inner/seckill/submitOrder")
    public Long submitOrder(@RequestBody OrderInfo orderInfo) {
        Long orderId = orderService.saveOrderInfo(orderInfo);
        return orderId;
    }

}
